import bpy

import 全局控制.Node.节点和插座基类.bl_节点基类 as 基类
import 全局控制.Node.插座.bl_插座基类 as 插座基类
#import 物体.物理管理.engine_物理体创建 as 物理体

from 节点.Core import bl_UI配色
from 物体.物体管理 import engine_物体创建

import engine.initLIB.load_dll as engineLib
import ctypes





engineLib.flexCAPI.f_创建物理体添加到引擎节点.restype = ctypes.c_bool
engineLib.flexCAPI.f_创建_置物理体变换_节点.restype = ctypes.c_bool
engineLib.flexCAPI.f_创建物体碰撞回调节点.restype = ctypes.c_bool
engineLib.flexCAPI.f_创建物理模拟更新节点.restype = ctypes.c_bool





g_物理_静态 = []
g_物理_刚体 = []




class C_Node_物理引擎_添加平面(基类.C_Node_基类):
	bl_dname = 'bl_node_物理引擎_添加平面'
	bl_label = '添加 PX 平面'
	
	m_Code = bpy.props.StringProperty()
	
	def init(self, context):
		super(C_Node_物理引擎_添加平面, self).f_init(context)
		self.inputs.new('C_Socket_I32', name='场景ID')
		self.inputs.new('C_Socket_平面', name='平面')
		
	def f_toCPP(self):
		engineLib.flexCAPI.f_创建物理平面节点(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name), self.f_getPyObject());


class C_NODE_AddMenu_物理引擎_添加平面(bpy.types.Operator):
	bl_idname = 'node.global_node_physics_add_px_plane'
	bl_label = '添加 PX 平面'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_物理引擎_添加平面', use_transform=True)
		return {'FINISHED'}





def f_update_物体设置碰撞回调(self, context):
	engineLib.flexCAPI.f_node_传入BL数据(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name), ctypes.py_object(self.m_加入));
	if context :
		self.id_data.f_节点数据更新_更新树([self])

class C_Node_添加物理体到引擎(基类.C_Node_基类):
	bl_dname = 'bl_node_物理引擎_添加物理体'
	bl_label = '添加物理体到引擎'
	
	m_加入 = bpy.props.BoolProperty(default=False, update=f_update_物体设置碰撞回调)
	def init(self, context):
		super(C_Node_添加物理体到引擎, self).f_init(context)
		self.inputs.new('C_Socket_I32', name='场景ID')
		self.inputs.new('C_Socket_物体_Array1D', name='物理体')
		self.outputs.new('C_Socket_物体_Array1D', name='场景物理体')
		self.f_toCPP(self.id_data)
		
	def draw_buttons(self, context, layout):
		layout.prop(self, 'm_加入')
		
	def f_toCPP(self, tree):
		新创建 = engineLib.flexCAPI.f_创建物理体添加到引擎节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 新创建 :
			self.use_custom_color = True
			self.color = bl_UI配色.g_物理节点颜色
		

class C_NODE_MENU_添加物理体到引擎(bpy.types.Operator):
	bl_idname = 'node.physics_node_add_body_to_scene'
	bl_label = '添加物理体到引擎'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_添加物理体到引擎', use_transform=True)
		return {'FINISHED'}














class C_Node_置物理体变换(基类.C_Node_基类):
	bl_dname = 'bl_node_置物理体变换'
	bl_label = '置物理体变换'
	
	def init(self, context):
		super(C_Node_置物理体变换, self).f_init(context)
		self.inputs.new('C_Socket_I32', name='场景ID')
		self.inputs.new('C_Socket_物体_Array1D', name='场景物理体')

		self.inputs.new('C_Socket_Vec3_Array1D', name='初始化坐标')
		self.inputs.new('C_Socket_Vec3_Array1D', name='初始化旋转')
		self.inputs.new('C_Socket_Vec3_Array1D', name='初始化速度')
		
		self.f_toCPP(self.id_data)
		
	def f_toCPP(self, tree):
		是否更新 = engineLib.flexCAPI.f_创建_置物理体变换_节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 是否更新 :
			self.use_custom_color = True
			self.color = bl_UI配色.g_物理节点颜色

			for i in range(3, len(self.inputs)):
				self.inputs[i].f_update()

class C_NODE_AddMenu_置物理体变换(bpy.types.Operator):
	bl_idname = 'node.global_node_set_physical_body_transform'
	bl_label = '置物理体变换'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_置物理体变换', use_transform=True)
		return {'FINISHED'}
		
	










class C_Node_物体碰撞回调(基类.C_Node_基类):
	bl_dname = 'bl_node_置物理体变换'
	bl_label = '置物理体变换'
	
	def init(self, context):
		super(C_Node_物体碰撞回调, self).f_init(context)
		self.inputs.new('C_Socket_I32', name='场景ID')
		self.inputs.new('C_Socket_物体_Array1D', name='场景物理体')

		self.outputs.new('C_Socket_物体_Array1D', name='物体A')
		self.outputs.new('C_Socket_Vec3_Array1D', name='碰撞坐标A')
		
		self.outputs.new('C_Socket_物体_Array1D', name='物体B')
		self.outputs.new('C_Socket_Vec3_Array1D', name='碰撞坐标B')

		self.outputs.new('C_Socket_F32_Array1D', name='碰撞距离')
		self.outputs.new('C_Socket_F32_Array1D', name='碰撞冲量')
		self.outputs.new('C_Socket_I32_Array1D', name='碰撞周期')
		
		self.f_toCPP(self.id_data)
		
	def f_toCPP(self, tree):
		是否更新 = engineLib.flexCAPI.f_创建物体碰撞回调节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		if 是否更新 :
			self.use_custom_color = True
			self.color = bl_UI配色.g_物理节点颜色

class C_NODE_AddMenu_物体碰撞回调(bpy.types.Operator):
	bl_idname = 'node.global_node_set_physical_body_collision_callback'
	bl_label = '物体碰撞回调'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_物体碰撞回调', use_transform=True)
		return {'FINISHED'}












E_物理对象结构更新类型枚举 = [
	("TYPE_单层物体", "单层物体", "", 0),
	("TYPE_多层子物体", "多层子物体", "", 1),
]

def f_update_对象结构更新类型(self, context):
	data = list(str(self.m_对象结构更新类型))
	engineLib.flexCAPI.f_node_传入BL数据(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name), ctypes.py_object(data));

def f_update_开启所有物体碰撞回馈(self, context):
	if self.m_开启所有物体碰撞回馈 :
		data = list(str('TYPE_开启碰撞回馈'))
	else:
		data = list(str('TYPE_关闭碰撞回馈'))
	engineLib.flexCAPI.f_node_传入BL数据(ctypes.c_wchar_p(self.id_data.name), ctypes.c_wchar_p(self.name), ctypes.py_object(data));

	if len(self.outputs) > 3:
		for i in range(3, len(self.outputs)) :
			if self.m_开启所有物体碰撞回馈 :
				self.outputs[i].hide = False
			else:
				self.outputs[i].hide = True

class C_Node_物理模拟更新(基类.C_Node_基类):
	bl_dname = 'bl_node_物理模拟更新'
	bl_label = '物理模拟更新'
	
	m_对象结构更新类型 = bpy.props.EnumProperty(items=E_物理对象结构更新类型枚举, update=f_update_对象结构更新类型)
	m_开启所有物体碰撞回馈 = bpy.props.BoolProperty(update=f_update_开启所有物体碰撞回馈)
	def init(self, context):
		super(C_Node_物理模拟更新, self).f_init(context)
		self.inputs.new('C_Socket_I32', name='场景ID')
		self.inputs.new('C_Socket_F32', name='每秒帧率')

		self.outputs.new('C_Socket_物体_Array1D', name='物体')
		self.outputs.new('C_Socket_矩阵4X4_Array1D', name='物体矩阵')

		#---------------- 碰撞回调 ---------------
		self.outputs.new('C_Socket_物体_Array1D', name='物体A')
		self.outputs.new('C_Socket_Vec3_Array1D', name='坐标A')
		
		self.outputs.new('C_Socket_物体_Array1D', name='物体B')
		self.outputs.new('C_Socket_Vec3_Array1D', name='坐标B')

		self.outputs.new('C_Socket_F32_Array1D', name='距离')
		self.outputs.new('C_Socket_F32_Array1D', name='冲量')
		self.outputs.new('C_Socket_I32_Array1D', name='周期')

		
		self.f_toCPP(self.id_data)

		self.inputs['每秒帧率'].f_setData(60.0)
		
	def draw_buttons(self, context, layout):
		layout.prop(self, 'm_对象结构更新类型')
		layout.prop(self, 'm_开启所有物体碰撞回馈', text='碰撞回馈')

	def f_toCPP(self, tree):
		是否更新 = engineLib.flexCAPI.f_创建物理模拟更新节点(ctypes.c_wchar_p(tree.name), ctypes.c_wchar_p(self.name), self.f_getPyObject(tree));
		
		if 是否更新 :
			#self.inputs['每秒帧率'].f_update()
			self.use_custom_color = True
			self.color = bl_UI配色.g_物理节点颜色
			
			f_update_对象结构更新类型(self, None)

			
		

class C_NODE_AddMenu_物理模拟更新(bpy.types.Operator):
	bl_idname = 'node.global_node_physical_simulation_update'
	bl_label = '物理模拟更新'
	bl_options = {'REGISTER', 'UNDO'}
	def execute(operator, context):
		bpy.ops.node.add_node(type='C_Node_物理模拟更新', use_transform=True)
		return {'FINISHED'}








classes = (
	C_Node_物理引擎_添加平面,
	C_NODE_AddMenu_物理引擎_添加平面,
	
	C_Node_添加物理体到引擎,
	C_NODE_MENU_添加物理体到引擎,

	C_Node_置物理体变换,
	C_NODE_AddMenu_置物理体变换,


	C_Node_物理模拟更新,
	C_NODE_AddMenu_物理模拟更新,

)

def register():
	for c in classes:
		bpy.utils.register_class(c)
		
def unregister():
	for c in classes:
		bpy.utils.unregister_class(c)




